# -*- coding: utf-8-*-
import datetime
from openerp import models, api, SUPERUSER_ID
from openerp.osv import osv, fields, orm


class sale_order(osv.osv):
    _inherit = 'sale.order'

    def check_product(self, cr, uid, ids, context=None):
        '''  一个产品不能同时出现在多个订单行里  '''
        order = self.browse(cr, uid, ids, context=context)
        res = []
        if order and order[0].order_line:
            for order_line_type in order[0].order_line:
                # 判断当前输入的产品在该销售订单已有产品中是否存在
                if order_line_type.product_id in res:
                    return False
                res.append(order_line_type.product_id)
        return True

    _columns = {
        'is_card': fields.boolean(u'卡券订单'),
        'is_active': fields.boolean(u'激活'),
        'by_agents': fields.boolean(u'代理商自助下单', readonly=True),
        'sale_order_id': fields.one2many('order.card', 'order_id', u'订单券号列表'),
    }

    _defaults = {
        'by_agents': lambda self, cr, uid, context: context.get('purchase_order_by_agents'),
        'is_card': lambda self, cr, uid, context: context.get('default_is_card'),
    }

    _constraints = [(check_product, u'一个订单中不能存在多个同种产品', ['order_line'])]


class order_card(osv.osv):
    _name = 'order.card'

    def unlink(self, cr, uid, ids, context=None):
        for order_card_obj in self.browse(cr, uid, ids, context=context):
            if order_card_obj.is_shipped:  # 判断卡券是否已发货
                raise osv.except_osv(u'错误', u'%s订单已发货')
            # 循环得出订单明细表里存在的对外编号列表
            for code in self.pool['product.card.issue'].get_exist_codes(cr, uid, order_card_obj.product_id, order_card_obj.starting_number.code, order_card_obj.continue_number, context=context):
                # 通过对外编号找出卡券(card_id),并释放锁定
                card_id = self.pool["product.card.line"].search(
                    cr, uid, [('code', '=', code), '|', ('active', '=', False), ('active', '=', True)])
                card_obj = self.pool["product.card.line"].browse(
                    cr, uid, card_id, context=context)
                card_obj.write({'delivery_lock': False})
        return super(order_card, self).unlink(cr, uid, ids, context=context)

    def create(self, cr, uid, vals, context=None):

        if vals.get('order_id', False):
            order_id = vals.get('order_id')
        # 独立创建出库单时，'order_id'字段无值
        else:
            order_id = self.default_get(
                cr, SUPERUSER_ID, ['order_id'], context=context).get('order_id')
        card = self.pool['product.card.line'].browse(
            cr, uid, vals.get("starting_number"), context=context)
        vals.update({'publish_date':card.publish_date})
        sale_line_id = self.pool['sale.order.line'].search(
            cr, uid, ['&', ('order_id', '=', order_id), ('product_id', '=', card.product_id.id)], context=context)
        order_obj = self.pool['sale.order'].browse(
            cr, uid, order_id, context=context)
        sale_line_num = 0
        if order_obj.product_id.is_card and order_obj.product_id.type == 'service':
            # 激活服务订单无需检查
            vals.update({'is_active': True})
            return super(order_card, self).create(cr, uid, vals, context=context)

        if sale_line_id:  # 订单行必须有产品
            for sale_order_line_id in sale_line_id:  # 统计产品种类和数量
                sale_line_obj = self.pool['sale.order.line'].browse(
                    cr, uid, sale_order_line_id, context=context)
                sale_line_num += sale_line_obj.product_uom_qty
        else:
            raise osv.except_osv(u'错误', u'订单中没有添加此产品')
        # 统计卡券订单中，所选卡券的已经存在的  产品的数量  对比已经存在的产品数量
        order_card_ids = self.pool['order.card'].search(
            cr, uid, ['&', ('order_id', '=', order_id), ('product_id', '=', card.product_id.id)])
        same_card_num = 0
        for order_card_id in order_card_ids:
            order_card_obj = self.pool['order.card'].browse(
                cr, uid, order_card_id, context=context)
            same_card_num += order_card_obj.continue_number
        # 核对卡券订单表中的本订单的产品的数量，和销售订单中的本产品

        continue_number = vals.get("continue_number", 1)
        flag = 1  # 卖出
        if sale_line_num < 0:
            flag = 0  # 退货
            sale_line_num = -sale_line_num
        if sale_line_num < continue_number + same_card_num:  # 判断订单中本产品的数量，和卡券订单行的本产品的数量一致
            raise osv.except_osv(u'错误', u'已输入的券号数量大于销售订单中此产品数量')

        for code in self.pool['product.card.issue'].get_exist_codes(cr, uid, card.product_id, card.code, continue_number, context=context):
            card_id = self.pool["product.card.line"].search(
                cr, uid, [('code', '=', code), '|', ('active', '=', False), ('active', '=', True)])
            card_obj = self.pool["product.card.line"].browse(
                cr, uid, card_id, context=context)
            if card_obj.is_exchanged == True:
                raise osv.except_osv(u'错误', u'券号%s已被兑换' % code)
            if card_obj.is_enabled == False:
                raise osv.except_osv(u'错误', u'券号%s没有启用' % code)
            if card_obj.delivery_lock:
                order_card_id = self.search(
                    cr, uid, [('ending_number', '>=', card_obj.code), ('starting_number_copy', '<=', card_obj.code)], context=context)
                order_card_obj = self.browse(
                    cr, uid, order_card_id, context=context)
                raise osv.except_osv(u'错误', u'券号%s已经被发货单%s锁定' % (
                    code, order_card_obj.picking_id.name))
            context.update({'company_partner_id':1})
            if flag == 0 and card_obj.owner_id.id == context['company_partner_id']:
                raise osv.except_osv(u'错误', u'券号%s目前已属于本公司无法入库' % code)
            elif flag == 1 and card_obj.owner_id.id != context['company_partner_id']:
                raise osv.except_osv(u'错误', u'券号%s目前不属于本公司无法发货' % code)
            card_obj.write({'delivery_lock': True})
        return super(order_card, self).create(cr, uid, vals, context=context)

    # onchange方法，判断起始券号连续可用数量是否足够
    def onchange_end_number(self, cr, uid, ids, starting_number, continue_number, context=None):
        if starting_number and continue_number:
            card_line_obj = self.pool.get('product.card.line').browse(
                cr, uid, starting_number, context=context)

            # 获得卡券明细中该卡券的列表
            code = self.pool.get("product.card.issue").get_exist_codes(
                cr, uid, card_line_obj.product_id, card_line_obj.code, continue_number, context=context)
            if len(code) == continue_number:
                return {'value': {'continue_number': continue_number}}
            else:
                return {'warning': {'title': u'警告', 'message': u'此起始券号连续可用数量不足'}, 'value': {'continue_number': 1}}
    # 在加载页面时动态的对start_number进行domain过滤。出库时必须是属于自己的，入库时，卡券的归属方必须是不属于自己的

    def onchange_picking_id(self, cr, uid, ids, picking_id, context=None):
        picking_obj = self.pool.get("stock.picking").browse(
            cr, uid, picking_id, context=context)
        if picking_obj.picking_type_code == "incoming":
            return {'domain': {'starting_number': [('level_one_partner_id', '=', picking_obj.partner_id.id)]}}
        else:
            return {'domain': {'starting_number': [('level_one_partner_id', '=', False)]}}

    # 获取结束券号
    def end_number(self, cr, uid, ids, field_name, arg, context=None):
        res = {}
        for line in self.browse(cr, uid, ids, context=context):
            card_line_obj = self.pool.get('product.card.line').browse(
                cr, uid, line.starting_number.id, context=context)
            # 获得卡券明细中该卡券的列表
            res[line.id] = self.pool.get("product.card.issue").get_next_n_number(cr, card_line_obj.code, line.continue_number - 1)
        return res
    _columns = {
        'order_id': fields.many2one('sale.order', u'订单号', domain=[('state', 'not in', ['draft', 'done'])]),
        'picking_id': fields.many2one('stock.picking', u'发货单号'),
        'starting_number': fields.many2one('product.card.line', u'起始号码id', domain=[('delivery_lock', '=', False), ('is_exchanged', '=', False), ('is_enabled', '=', True)], required=True),
        'starting_number_copy': fields.related('starting_number', 'code', type="char", string=u'起始号码', store=True, readonly='1'),
        'product_id': fields.related('starting_number', 'product_id', type='many2one', relation='product.product', string=u'产品名称', store=True, readonly='1'),
        # 标识该记录是否在卡券激活或者取消激活时创建
        'is_active': fields.boolean(u'是否激活'),
        'continue_number': fields.integer(u'卡券数量', required=True),
        'ending_number': fields.function(end_number, type='char', string=u'结束券号', store=True),
        'is_shipped': fields.boolean(u'是否发货'),
        'amount': fields.float(u'金额', digits=(16, 2)),
        'partner_id': fields.related('order_id', 'partner_id', type='many2one', relation='res.partner', string=u'客户', store=True, readonly=True),
        'is_return': fields.related('order_id', 'is_return', type='boolean', string=u'是否退单'),
        'shipped_date': fields.date(u'发货日期'),
        'publish_date': fields.datetime(u'卡券发行日期')
    }

    _defaults = {
        'picking_id': lambda self, cr, uid, context: context.get('active_id'),
        'order_id': lambda self, cr, uid, context: self.pool.get('stock.picking').browse(cr, uid, context.get('active_id'), context=context).sale_id.id,
        'continue_number': 1,
    }


class sale_order_line(osv.osv):
    _inherit = 'sale.order.line'
    _columns = {
        'product_id': fields.many2one('product.product', 'Product', required=True, domain=[('sale_ok', '=', True)], change_default=True, readonly=True, states={'draft': [('readonly', False)]}, ondelete='restrict'),
        'floor_price': fields.float(string=u'最低售价'),
    }
    # 订单产品更改时，若是卡券产品更新单价，并把产品单价存入最低售价字段

    def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,
                          uom=False, qty_uos=0, uos=False, name='', partner_id=False,
                          lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, context=None):
        products = self.pool.get('product.product')
        res = super(sale_order_line, self).product_id_change(cr=cr, uid=uid, ids=ids, pricelist=pricelist, product=product, qty=qty,
                                                             uom=uom, qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id,
                                                             lang=lang, update_tax=update_tax, date_order=date_order, packaging=packaging, fiscal_position=fiscal_position, flag=flag, context=context)
        product_obj = products.browse(cr, uid, product, context=context)

        if product_obj.is_card:
            res['value'].update({'price_unit': 0})

        if res['value'].has_key('price_unit'):
            res['value']['floor_price'] = res['value']['price_unit']

        return res

    def onchange_price_unit(self, cr, uid, ids, product_id, floor_price, price_unit, context=None):
        # 卡券订单的成本价等于0判断
        product_obj = self.pool.get("product.product").browse(
            cr, uid, product_id, context=context)
        if product_obj.is_card:
            if floor_price != 0:
                return {'warning': {'title': u'警告', 'message': u'卡券产品必须价格为零'}}

        # 单价比最低售价小，给出警告并更新单价为最低售价
        if (floor_price > 0) and (price_unit < floor_price):
            return {'warning': {'title': u'警告', 'message': u'不能低于最低售价%s' % floor_price}, 'value': {'price_unit': floor_price}}


class stock_picking(osv.osv):
    _inherit = 'stock.picking'

    # 判断是否是卡券移库单
    def get_is_card(self, cr, uid, ids, name, args, context=None):
        sale_obj = self.pool.get("sale.order")
        res = {}
        for picking in self.browse(cr, uid, ids, context=context):
            sale_id = sale_obj.search(
                cr, uid, [('name', '=', picking.origin)], context=context)
            if sale_id:
                sale_obj_d = sale_obj.browse(cr, uid, sale_id, context=context)
                res[picking.id] = sale_obj_d.is_card
            else:
                res[picking.id] = False
        return res

    def unlink(self, cr, uid, ids, context=None):
        order_card_id = self.pool.get('order.card').search(
            cr, uid, [('picking_id', '=', ids[0])], context=context)
        self.pool.get('order.card').unlink(
            cr, uid, order_card_id, context=context)
        return super(stock_picking, self).unlink(cr, uid, ids, context=context)

    def action_cancel(self, cr, uid, ids, context=None):
        order_card_id = self.pool.get('order.card').search(
            cr, uid, [('picking_id', '=', ids[0])], context=context)
        self.pool.get("order.card").unlink(
            cr, uid, order_card_id, context=context)
        super(stock_picking, self).action_cancel(cr, uid, ids, context=context)

    _columns = {
        'order_card_id': fields.one2many("order.card", 'picking_id', u'订单券号列表'),
        'is_card': fields.function(get_is_card, type='boolean', string='是否是卡券移库单', store=True),
    }


class stock_transfer_details(osv.TransientModel):

    _inherit = 'stock.transfer_details'

    @api.one
    def do_detailed_transfer(self):
        '''  卡券产品发货时更新卡券信息  '''
        res = {}  # 查出要出库的产品的列表和数量，核对卡券中订单券号列表中的订单的卡券数量，如果不对应则，报错。
        if self.picking_id.sale_id.is_card:
            ''' 按产品汇总数量'''
            product_issue_obj_old = self.pool['product.card.issue']
            product_track_obj_new = self.env['product.card.track']
            product_line_obj_new = self.env['product.card.line']
            product_line_obj_old = self.pool['product.card.line']
            product_index_obj_old = self.pool['product.card.index']
            product_index_obj_new = self.env['product.card.index']
            for item in self.item_ids:
                if res.has_key(item.product_id.id):
                    res[item.product_id.id] += item.quantity
                else:
                    res.update({item.product_id.id: item.quantity})
            # 查出order_card中的订单的产品的数量，并根据产品id和产品的数量核对，
            user_obj = self.pool["res.users"].browse(
                self._cr, self._uid, self._uid, context=self._context)
            if self.picking_id.picking_type_code == "outgoing":
                flag = 1
            elif self.picking_id.picking_type_code == "incoming":
                flag = 0
            card_ids = []
            card_ids_all = []
            all_codes = []
            for key in res.keys():
                all_number = 0
                # order_line=self.env['sale.order.line'].search([('product_id','=',key)])[0]
                # 循环得出order_card中，卡券产品在待出库的销售订单中存在且未发货的列表
                for order_card in self.env['order.card'].search(['&', '&', ('order_id', '=', self.picking_id.sale_id.id), ('starting_number.product_id', '=', key), ('is_shipped', '=', False)]):
                    # 统计数量并把发货状态及时间存入order_card表
                    all_number += order_card.continue_number
                    order_card.sudo().write(
                        {'is_shipped': True, 'shipped_date': datetime.datetime.now()})  # 在order_card表中标记已发货
                    codes = product_issue_obj_old.get_exist_codes(
                        self._cr, self._uid, order_card.product_id.id, order_card.starting_number.code, order_card.continue_number, context=self._context)
                    card_lines = product_line_obj_new.search(
                        [('code', 'in', codes), '|', ('active', '=', False), ('active', '=', True)])
                    all_codes.extend(codes)
                    for card_line in card_lines:
                        # 判断卡券明细列表中是否存在卡券发行列表行，并释放订单发货锁定
                        if not card_line:
                            raise osv.except_osv(
                                u'警告！', u'%s不存在卡券' % card_line.code)
                        # 如果是出库订单
                        if flag == 1:
                            # 在日志表(track)中增加一条记录，表明产品owner的归属变更,记录operation_type
                            product_track_obj_new.create({'card_line_id': card_line.id, 'code': card_line.code,
                                                          'old_owner_id': card_line.owner_id.id, 'new_owner_id': self.picking_id.partner_id.id,
                                                          'operation_type': 'sold',
                                                          })
                            # 新建index记录
                            product_index_obj_new.create(
                                {'owner_id': self.picking_id.partner_id.id, 'card_line_id': card_line.id, 'code': card_line.code, 'product_id': card_line.product_id.id})
                            card_ids.append(card_line.id)
                        # 如果是入库订单
                        else:
                            card_ids_all.append(card_line.id)
                            if card_line.is_active:
                                card_ids.append(card_line.id)
                            # 增加一条日志表（track）记录, 更新owner并记录operation_type
                            product_track_obj_new.create({'card_line_id': card_line.id, 'code': card_line.code,
                                                          'old_owner_id': self.picking_id.partner_id.id, 'new_owner_id': self._context['company_partner_id'],
                                                          'operation_type': 'back',
                                                          })
                    continue
                # 如果是出库单
                if res[key] != all_number:
                    if flag == 1:
                        raise osv.except_osv(
                            u'错误', u'出库数量与订单券号列表中的量不符,可能是\n 1.移库产品和订单产品不符\n 2.移库产品数量和订单产品数量不符\n 请返回到出库单上点击【输入券号】按钮')
                    else:
                        raise osv.except_osv(
                            u'错误', u'入库库数量与订单券号列表中的量不符，可能是\n 1.移库产品和订单产品不符\n 2.移库产品数量和订单产品数量不符\n 请返回到出库单上点击【输入券号】按钮')
            if flag == 1:
                all_card_lines = product_line_obj_new.search(
                    [('id', 'in', card_ids), '|', ('active', '=', False), ('active', '=', True)])
                # 更新归属表(index)，原卡券记录中显示为已售出
                old_index = product_index_obj_new.search(['&', ('code', 'in', all_codes), (
                    'is_sold_out', '=', False), ('owner_id', '=', all_card_lines[0].owner_id.id)])
                old_index.write({'is_sold_out': True})
                # 卡券产品已激活，则警告
                # 修改card_line表中的owner
                all_card_lines.write({'owner_id': self.picking_id.partner_id.id,
                                      'level_one_partner_id': self.picking_id.partner_id.id, 'delivery_lock': False})
                if self.picking_id.sale_id.is_active:
                    message = product_line_obj_old.do_active(
                        self._cr, self._uid, card_ids, context=self._context)
                    if message:
                        raise osv.except_osv('警告！', message)
            # 如果是入库单
            else:
                message = product_line_obj_old.do_deactive(
                    self._cr, self._uid, card_ids, context=self._context)
                # 修改cardline表中的owner
                product_line_obj_old.write(self._cr, self._uid, card_ids_all, {'owner_id': self._context[
                                           'company_partner_id'], 'level_one_partner_id': None, 'level_two_partner_id': None, 'delivery_lock': False}, context=self._context)
                # index表中的原卡券记录中要显示已售出
                old_index = product_index_obj_old.search(self._cr, self._uid, [(
                    '&'), ('card_line_id', 'in', card_ids_all), ('owner_id', '=', self.picking_id.partner_id.id)], context=self._context)
                # 删除归属表中，旧归属的记录
                product_index_obj_old.unlink(self._cr, self._uid, old_index)
                new_index = product_index_obj_new.search(
                    [('card_line_id', 'in', card_ids_all), ('owner_id', '=', self._context['company_partner_id'])])
                new_index.write({'is_sold_out': False})
                if message:
                    raise osv.except_osv(u'警告！', message)
        return super(stock_transfer_details, self).do_detailed_transfer()
